package com.ams.controller;

import com.alibaba.fastjson.JSONObject;
import com.ams.common.entity.DataInsEntity;
import com.ams.common.entity.InsDetailEntity;
import com.ams.common.entity.InsEntity;
import com.ams.common.utils.R;
import com.ams.common.utils.RedisUtils;
import com.ams.common.utils.Retrys;
import com.ams.common.utils.SnConstant;
import com.ams.enums.*;
import com.ams.form.WcsCheckInForm;
import com.ams.model.*;
import com.ams.service.*;
import com.ams.service.impl.WcsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 微信小程序用户接口
 *
 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 */
@RestController
@Slf4j
@RequestMapping("/api")
public class WcsController {

    @Autowired
    EntrancePrivilegeService entrancePrivilegeService;

    @Autowired
    DocAsnHeaderService docAsnHeaderService;

    @Autowired
    DocAsnDetailsService docAsnDetailsService;

    @Autowired
    BasLocationService basLocationService;

    @Autowired
    DocOrderHeaderService docOrderHeaderService;

    @Autowired
    DocOrderDetailsService docOrderDetailsService ;

    @Autowired
    InvLotLocIdService invLotLocIdService ;

    @Autowired
    RedisUtils redisUtils ;

    @Autowired
    WcsService wcsService;

    @PostMapping("/checkin")
    public R checkin(@RequestBody WcsCheckInForm wcsCheckInForm){
        log.info("checkin start>>>>>>>>>>>>>" + wcsCheckInForm.getEntranceid());
        EntrancePrivilege entrancePrivilege = entrancePrivilegeService.findById(wcsCheckInForm.getEntranceid());
        if(entrancePrivilege == null) {
            return R.error(ResultEnum.API_ENTRANCEID_NOT_EXSITS);
        }
        log.info("checkin enter>>>>>>>>>>>>>");
        String trayId = "";
        String rackId = "";
        String locationId = "";
        String sku = "";
        BigDecimal from = BigDecimal.ZERO;
        BigDecimal to = BigDecimal.ZERO;
        log.info("wcsCheckInForm.getStatus() >>>>>>>>>>>>>>>>> {}", wcsCheckInForm.getStatus());
        // 进入
        if(wcsCheckInForm.getStatus() == 1) {
            entrancePrivilege.setEntrancestatus(EntranceStatus.ENTER.getMessage());
        }else if(wcsCheckInForm.getStatus() == 2) {// 退出
            entrancePrivilege.setEntrancestatus(EntranceStatus.EXIT.getMessage());
        }else {
            log.info("wcsCheckInForm state not extist status = {}", wcsCheckInForm.getStatus());
            return R.error(ResultEnum.API_ENTRANCE_STATUS_ERROR);
        }
        log.info("checkin enter>>>>>>>>>>>>> 222");
        // 判断是否是入库表
        if (entrancePrivilege.getOrderno().indexOf(SnConstant.DOC_ASN_PREFIX) > -1) {
            log.info("checkin 入库>>>>>>>>>>>>>");
            DocAsnHeader docAsnHeader = docAsnHeaderService.findById(entrancePrivilege.getOrderno());
            if (docAsnHeader == null) {
                return R.error(ResultEnum.API_ENTRANCE_ORDERNO_NOT_EXISTS);
            } else {
                docAsnHeader.setAsnstatus(OrderStatusEnum.OPERATION.getMessage());
                docAsnHeaderService.update(docAsnHeader);
            }

            // 批量预授权
            docAsnDetailsService.updateStatusByOrderNo(entrancePrivilege.getOrderno(), OrderDetailStatusEnum.OPERATION.getMessage());
            DocAsnDetails query = new DocAsnDetails();
            query.setAsnno(entrancePrivilege.getOrderno());
            query.setLinestatus(OrderDetailStatusEnum.OPERATION.getMessage());
            List<DocAsnDetails> docAsnDetailsList = docAsnDetailsService.findByModel(query);
            if (docAsnDetailsList != null && docAsnDetailsList.size() > 0) {
                log.info("checkin asn>>>>>>>>>>>>> 1");
                boolean isFirst = true;
                for (DocAsnDetails docAsnDetails : docAsnDetailsList) {
                    String matno = docAsnDetails.getSku();
                    BasLocation basLocationQuery = new BasLocation();
                    basLocationQuery.setSku(matno);
                    BasLocation basLocation = basLocationService.findFirstByModel(basLocationQuery);
                    if (isFirst) {
                        trayId = basLocation.getTrayId();
                        isFirst = false;
                    }
                    log.info("checkin asn>>>>>>>>>>>>> 2");
                    rackId = basLocation.getRackId();
                    locationId = basLocation.getLocationid();
                    log.info("checkin asn>>>>>>>>>>>>> 3");
                    sku = matno;
                    BigDecimal curStock = invLotLocIdService.getStockByLotId(rackId, locationId);
                    from = curStock.add(docAsnDetails.getReceivedqty());
                    to = curStock.add(docAsnDetails.getExpectedqty());
                    log.info("checkin link asn>>>>>>>>>>>>>rackId = {} locationId = {} from = {} to = {} trayId = {}", rackId, locationId, from, to, trayId);
                    retrySetPreAuthDelta(rackId, locationId, from, to);
                }

            }
        } else if (entrancePrivilege.getOrderno().indexOf(SnConstant.DOC_ORDER_PREFIX) > -1) {// 判断是否是出库表
            log.info("checkin 出库>>>>>>>>>>>>>");
            DocOrderHeader docOrderHeader = docOrderHeaderService.findById(entrancePrivilege.getOrderno());
            if (docOrderHeader == null) {
                return R.error(ResultEnum.API_ENTRANCE_ORDERNO_NOT_EXISTS);
            } else {
                docOrderHeader.setSostatus(OrderStatusEnum.OPERATION.getMessage());
                docOrderHeaderService.update(docOrderHeader);
            }
            docOrderDetailsService.updateStatusByOrderNo(entrancePrivilege.getOrderno(), OrderDetailStatusEnum.OPERATION.getMessage());
            DocOrderDetails query = new DocOrderDetails();
            query.setOrderno(entrancePrivilege.getOrderno());
            query.setLinestatus(OrderDetailStatusEnum.OPERATION.getMessage());
            List<DocOrderDetails> docOrderDetailsList = docOrderDetailsService.findByModel(query);
            if (docOrderDetailsList != null && docOrderDetailsList.size() > 0) {
                boolean isFirst = true;
                for (DocOrderDetails docOrderDetails : docOrderDetailsList) {
                    String matno = docOrderDetails.getSku();
                    BasLocation basLocationQuery = new BasLocation();
                    basLocationQuery.setSku(matno);
                    BasLocation basLocation = basLocationService.findFirstByModel(basLocationQuery);
                    if (isFirst) {
                        trayId = basLocation.getTrayId();
                        isFirst = false;
                    }
                    rackId = basLocation.getRackId();
                    locationId = basLocation.getLocationid();
                    sku = matno;
                    BigDecimal curStock = invLotLocIdService.getStockByLotId(rackId, locationId);
                    BigDecimal orrderStock = docOrderDetails.getQtyordered();
                    from = curStock.subtract(docOrderDetails.getQtyshipped());
                    to = curStock.subtract(orrderStock);
//                    String fromStr = from.toString();
//                    Double fromDbl = from.doubleValue();
//                    String toStr = to.toString();
//                    Double toDbl = to.doubleValue();
                    log.info("checkin link order>>>>>>>>>>>>>rackId = {} locationId = {} from = {} to = {} trayId = {}", rackId, locationId, from.intValue(), to.intValue(), trayId);
                    retrySetPreAuthDelta(rackId, locationId, from, to);
                }
            }
        } else {
            log.info("checkin error>>>>>>>>>>>>> API_ENTRANCE_STATUS_ERROR");
            return R.error(ResultEnum.API_ENTRANCE_STATUS_ERROR);
        }

        boolean succ = entrancePrivilegeService.update(entrancePrivilege);
        log.info("checkin upt succ>>>>>>>>>>>>>");
        if(succ) {
            // 进门
            if(wcsCheckInForm.getStatus() == 1) {
                this.clearCache();
                log.info("checkin link>>>>>>>>>>>>> {}", trayId);
                //吐出托盘
                wcsService.linkOperation(trayId, LinkOperationStatus.CALL.getCode());

                try {
                    wcsService.lightOperation(LightOperationStatus.NORMAL);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return R.ok();
        }
        return R.error(ResultEnum.SYSTM_ERROR);
    }

    private void retrySetPreAuthDelta(String rackId, String locationId, BigDecimal from, BigDecimal to) {
        String finalRackId = rackId;
        String finalLocationId = locationId;
        BigDecimal finalFrom = from;
        BigDecimal finalTo = to;
        try {
            Retrys.retry(() -> {
                wcsService.setPreAuthDelta(finalRackId, finalLocationId, finalFrom, finalTo);
                return true;
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @GetMapping("/initStock")
    public String initStock(){
        wcsService.initStock();
        return "success";
    }

    @GetMapping("/initPreAuthDelta")
    public String initPreAuthDelta(){
        wcsService.initPreAuthDelta();
        return "success";
    }

    @GetMapping("/trayReturn/{trayId}")
    public String trayReturn(@PathVariable("trayId") String trayId){
        wcsService.linkOperation(trayId, LinkOperationStatus.RETURN.getCode());
        return "success";
    }

    @GetMapping("/trayCall/{trayId}")
    public String trayCall(@PathVariable("trayId") String trayId){
        wcsService.linkOperation(trayId, LinkOperationStatus.RETURN.getCode());
        return "success";
    }

    @GetMapping("/mockWdsSendAsn")
    public String mockWdsSend(){
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        List<InsEntity> insEntityList = new ArrayList<>();
        InsEntity insEntity = new InsEntity();
        insEntity.setWhno("JAL2");
        insEntity.setBinnoTo("end");
        insEntity.setBinnoFrom("start");
        insEntity.setTaskno("t001");
        insEntity.setRfidCode("3");
        insEntity.setStoArea("A/01");
        insEntity.setOperateType(OrderTaskTypeEnum.STOCK_IN.getMessage());
        insEntity.setTaskSource("1");
        insEntity.setPalletLoc("aaa");
        insEntity.setTaskLevel(1);
        insEntity.setTaskTime("2019-10-01 10:00:00");
        List<InsDetailEntity> insDetailEntityList = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
            InsDetailEntity insDetailEntity = new InsDetailEntity();
            insDetailEntity.setMatno("SKU001");
            insDetailEntity.setMatText("desc");
            insDetailEntity.setQuantity(2.0F);
            insDetailEntity.setBatch("b001");
            insDetailEntityList.add(insDetailEntity);
        }

        insEntity.setReserve(insDetailEntityList);

        insEntityList.add(insEntity);
        DataInsEntity dataInsEntity = new DataInsEntity();
        dataInsEntity.setData(insEntityList);
        String data = JSONObject.toJSONString(dataInsEntity);

        sendWms1TaskResult(dcf, data);
        return "success";
    }

    @GetMapping("/mockWdsSendOrder")
    public String mockWdsSendAsn(){
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        List<InsEntity> insEntityList = new ArrayList<>();
        InsEntity insEntity = new InsEntity();
        insEntity.setWhno("JAL2");
        insEntity.setBinnoTo("end");
        insEntity.setBinnoFrom("start");
        insEntity.setTaskno("t001");
        insEntity.setRfidCode("3");
        insEntity.setStoArea("A/01");
        insEntity.setOperateType(OrderTaskTypeEnum.STOCK_OUT.getMessage());
        insEntity.setTaskSource("1");
        insEntity.setPalletLoc("aaa");
        insEntity.setTaskLevel(1);
        insEntity.setTaskTime("2019-10-01 10:00:00");
        List<InsDetailEntity> insDetailEntityList = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
            InsDetailEntity insDetailEntity = new InsDetailEntity();
            insDetailEntity.setMatno("SKU001");
            insDetailEntity.setMatText("desc");
            insDetailEntity.setQuantity(2.0F);
            insDetailEntity.setBatch("b001");
            insDetailEntityList.add(insDetailEntity);
        }

        insEntity.setReserve(insDetailEntityList);

        insEntityList.add(insEntity);
        DataInsEntity dataInsEntity = new DataInsEntity();
        dataInsEntity.setData(insEntityList);
        String data = JSONObject.toJSONString(dataInsEntity);

        sendWms1TaskResult(dcf, data);
        return "success";
    }

    @GetMapping("/wdsCancel")
    public String wdsCancel(){
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient("http://localhost:8080/ams/services/Wcs2wdsService?wsdl");
        // 需要密码的情况需要加上用户名和密码
        // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
        try {
            List<InsEntity> insEntityList = new ArrayList<>();
            InsEntity insEntity = new InsEntity();
            insEntity.setWhno("JAL2");
            insEntity.setBinnoTo("end");
            insEntity.setBinnoFrom("start");
            insEntity.setTaskno("t001");
            insEntity.setRfidCode("3");
            insEntity.setStoArea("A/01");
            insEntity.setOperateType(OrderTaskTypeEnum.STOCK_IN.getMessage());
            insEntity.setTaskSource("1");
            insEntity.setPalletLoc("aaa");
            insEntity.setTaskLevel(1);
            insEntity.setTaskTime("2019-10-01 10:00:00");
            List<InsDetailEntity> insDetailEntityList = new ArrayList<>();
            for (int i = 0; i < 1; i++) {
                InsDetailEntity insDetailEntity = new InsDetailEntity();
                insDetailEntity.setMatno("SKU001");
                insDetailEntity.setMatText("desc");
                insDetailEntity.setQuantity(2.0F);
                insDetailEntity.setBatch("b001");
                insDetailEntityList.add(insDetailEntity);
            }

            insEntity.setReserve(insDetailEntityList);

            insEntityList.add(insEntity);
            DataInsEntity dataInsEntity = new DataInsEntity();
            dataInsEntity.setData(insEntityList);
            String data = JSONObject.toJSONString(dataInsEntity);
            Object[] objects = client.invoke("CancelWms1TaskJson", data);
            if(objects.length>0){
                log.info("CancelWms1TaskJson result >>>>>>>>>>>> {}", objects);
            }
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
        return "success";
    }

    private void clearCache() {
        // 清空错误列表
//        redisUtils.delete(RedisKeys.RACK_MIS_LIST);
//        redisUtils.delete(RedisKeys.LINK_TRAY_ID);
    }

    private void sendWms1TaskResult(JaxWsDynamicClientFactory dcf, String data){
        Client client = dcf.createClient("http://localhost:8080/ams/services/Wcs2wdsService?wsdl");
        // 需要密码的情况需要加上用户名和密码
        // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
        try {

            Object[] objects = client.invoke("SendWms1TaskJson", data);
            if(objects.length>0){
                log.info("SendWms1TaskJson result >>>>>>>>>>>> {}", objects);
            }
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
    }



}
